Okay.
The next thing we need to script is our task service, which will be responsible for setting up the
tasks for the players to complete.
We're going to have a total of four tasks.
One is going to be where the player needs to clean any dirty tables.
So we have crumbs here that we can take out of the server storage real quick.
And we'll put this in the workspace.
And these crumbs will be positioned randomly around on each of these tables.
And the players must clean this up.
We also have another task where they're going to have to, uh, broom up or clean dirt off of the floor.
So these will be randomly positioned around the floor of our restaurant as well.
We also need to restock the kitchen fridge with food.
So what we'll do is we'll take these crates here and we're going to spawn four of these crates in.
And we're going to rotate them randomly.
And players can grab a can or something from this crate.
And they can walk over and take it.
And there will be a prompt in front of this fridge that the players can go ahead and put their food
inside of.
And then the last task we need to complete is cleaning out the water inside of our toilets.
So each toilet will have some dirty water placed inside of it, and the players must go and clean it
using this toilet scrubber here.
Each of these different tasks have proximity prompts in them inside of these attachments that the players
can use to, you know, go ahead and complete the task.
If at any point the players try to complete a task, but they don't have the necessary tool to complete
it.
So, for example, if they try to clean the dirt on the floor without grabbing the broom, or they try
to clean the toilets without grabbing the toilet brush, or they try to restock the kitchen without
any food on them, we can send a message to them using that update guy event to tell them that they
need a specific tool, or they need something to complete the task correctly.
So let's go ahead and move these back into server storage.
And we also have another folder in here that defines all the possible positions that we could place,
for example, our crumbs, our dirt, the toilet water, and then the positions for these food crates.
So for example, there's these little points on each of the tables that define where we can put the
crumbs at.
So we can put a maximum of six crumb tasks.
Same thing goes for the dirt.
We can place a maximum of six dirt tasks.
There's a maximum of three possible toilet tasks that we can do.
And then we just have four positions for the food crates.
Because the plan is, is that each food crate is going going to have a limited supply of food items
in them.
So for example, maybe there's only three different cans in each crate.
And you need a total of like let's say eight, uh, food items to fill up the fridge, whatever.
That's what we're going to be using those positions for.
So to get started we can open up our task service.
And inside of here we're going to need quite a few services.
We're going to need server script service.
We are going to need server storage.
We are going to need replicated storage.
We will need the player service.
We're going to need a service called the Proximity Prompt Service.
And then we're also going to need the sound service.
Now, what the Proximity prompt service does is it allows for us to listen for when a prompt is activated
in our game, instead of us having to reference prompts directly, we can just use this service which
has an event inside of it that gets fired every single time a prompt gets activated in the game, no
matter what prompt it is.
And then we can check to see if this prompt matches any of the prompts within our tasks item, and then
do whatever according to the specific prompt that was activated.
Next, we can go ahead and create the table that will represent our task service.
And we'll make sure to return it at the end of our script here.
And then now we can make some other variable references.
We need to reference our update guy event, replicated storage, dot events, dot remotes, dot update
guy.
We're going to have to get the guy actions enum.
So we'll require from replicated storage dot modules dot enums, dot guy actions enum.
We'll get the game comms event on the server, so we can call this game comms Bindable.
And that's going to be in server storage, dot events, dot Bindable dot game comms.
And then we can get the game comms enum for the server.
So we'll require that from server script service dot server dot modules, dot enums dot game communication
enum.
And then we're going to get the game comms event replicated storage dot events, dot remotes, dot game
communication.
And then we can get the game comms enum for the client as well.
Replicated storage dot modules dot enums, dot game communication enum.
And then one last event we're going to make a reference to is a another Bindable event in server storage
we're going to call it Tasks Service Bindable which is in server storage, dot events dot Bindesboll's
dot task service Bindable.
And we're going to use this event to listen for when we are told to set up all of the tasks in our game.
So this is going to be the bindable that we need to use to communicate with the service.
And as such, what we could do is we could go into our server script service, go into our game communication
enum, and we can go ahead and create a new section for the task service.
And the actions that we could do in here, for example, is to tell the service to set up tasks.
We could also give the action to disable the task, so this will end it once either our time is up or
we've already completed all of the tasks.
And then we could also give an action to, um, perhaps get some completed task for a particular player,
because later down the road, when the game ends, we want to show the, uh, player how many tasks
they completed, and only the task service is going to know that.
So we can have an action of like get completed tasks for player.
And this could return back to us all of the completed tasks for that particular player.
And that's what we're going to use our task service Bindable for, because this is actually if I retype
it out, this is actually a bindable function.
So we can send information to it.
And we can also get information back.
Now another uh, variable I want to make is to make a reference to a proximity prompt inside of the
workspace.
So we're going to call it referral prompt.
And that's in the workspace dot Krusty Krab.
We'll get the fridge that's in the kitchen.
And then inside of the primary part of the fridge there's an attachment.
And attachment has a proximity prompt inside of it.
So this is the proximity prompt that we're going to use with our fridge to refill it.
So inside of the main body there's an attachment.
And right here is going to be a proximity prompt where we can fulfill it and refill the fridge.
Uh, ensuring that the player actually has food items in their hand.
The next thing I'm going to do is I'm going to create a table.
We'll call it tasks.
And this will store all of the tasks that the players need to complete.
So one of the tasks we'll call it dirt.
And we can give text for this particular task to give to the player.
So this one we need to sweep the floor.
And we're going to put a coin in an empty space here because later we're going to concatenate the string
with how many, um, you know, tasks left they need to do.
So maybe they have three out of 5 or 1 out of two, whatever.
We're going to keep track of whether or not this task was fulfilled.
False is default.
And then we can define whether or not we need a tool to complete this task.
Since we need a broom to sweep the dirt off the floor, we can say, yep, there's a required tool.
And that required tools name is going to be broom.
Lastly, we could also create a key for a completion sound when a player completes the task.
So just to improve the ambience a little bit more, when the player completes this task, we can play
a sound like sweeping.
So inside of the sound service inside of the SFX folder we have a sound called Broom Sweep.
So if we go into the sound service.
Inside of here.
Inside of SFX.
Here is our broom sweep sound.
So when the player completes the broom task, we'll play this.
And we'll do the same thing for when they clean the tables.
When they clean the toilets, we'll play this sound.
And when we want to place an item in the fridge, we can play this sound and some other sounds we have
in here as well.
The next task, for example, is cleaning up crumbs off of the table.
So the text for this one is going to be, uh, wipe the tables.
Fulfilled is going to be false.
There's not going to be any required tool, so we don't have to specify that.
But we do have a completion sound.
And that's going to be the same sound service dot SF dot broom sweep.
The next task that we can do is we'll call it dirty water.
Or this is for our toilets.
So the text for this one is going to be clean the toilets.
Fulfilled is equal to false.
We do have a required tool for this one.
And that's going to be our toilet brush.
So the name of that tool is just toilet brush.
And then we can set the completion sound equal to sound service dot sfx dot toilet flush.
And then the last task is for our food crates.
This one's a little bit special because there's going to be two different things involved with our food
Crate task.
First, the players need to collect an item out of the food crates that will spawn over here, and then
they need to take an item and place it inside of the fridge so we can define the text for this, which
will be.
Stock the kitchen.
Fulfilled also will be false.
Now we're going to have a sound to play when the players collect something out of the crate, so we
can call it collection sound, and that's going to be equal to the sound service SFX, dot crate sound.
And then we're also going to have a completion sound.
So that's going to be sound service dot SFX dot place item in fridge.
After this we're going to create a random data type.
And then I'm also going to make a reference to some other sounds in the sound service.
One is going to store all of the different music that we have for tasks.
So inside of the ambience folder we have a folder called music.
And inside of here we have another folder called Task Music.
And what we could do is we could grab one of these sound instances and play it when the players have
to, you know, go clean up tasks.
So that way we could play music like this, or we could play music like this, or we could play music
like this one.
So we're just going to pick randomly out of the three music instances that we have here.
And we're going to play it.
So we're going to make a reference to all of the different task musics that we have.
So that's going to be in sound service dot ambience, dot music, dot task music.
And we're going to get all the children in there.
And then we can have another variable to keep track of what that chosen music is so chosen music and
we can set it randomly.
So it's going to be equal to task music.
And we're going to get a random one out of there using RNG.
Next integer one to the number of elements inside of our task music table.
And then what I'm also going to do is I'm going to create another table.
And we're going to call this Total tasks.
And this is going to keep track of the current amount of tasks that we have, how many we have fulfilled
and like what's the max amount that we can have.
So for our task for now, I'm just going to set the max equal to one.
The total that we currently have is zero, and the amount that we have fulfilled is zero as well.
And I'm just going to copy this and we can do the same thing for the crumbs.
Paste it again.
We could do the same thing for our dirty water task.
And then one last time we're going to do the same thing for the food crates task.
Now you can of course increase or change these values.
Just make sure they don't exceed, you know, the maximum amount of positions that we have on the map
for the different tasks.
But this table will help us keep track of exactly how many the players have fulfilled.
And then if they, you know, reach the total of fulfilled, then we can tell them that they completed
that particular task.
And the last but not least, we're also going to create a table to keep track of the different totals
for players, so we can call it player task totals, and this will keep track for us the different tasks
that players have completed.
So this will universally keep track of the total tasks completed.
And then this will break it down into different players.
So which player completed what task.
Now some private functions we're going to need.
One is to check the completion of the tasks so we can call it check task completion.
And this will return true or false.
Whether or not we have completed all the tasks, we need a function to listen for when a prompt gets
triggered from our proximity prompt service so we can call it on prompt triggered.
And this function gets passed a prompt instance.
So we can just call it prompt object.
And then it also gets the player that triggered the prompt.
So this is going to be a player.
And then this is going to be a proximity prompt.
We're also going to need a function to listen for when a prompt, you know first gets pressed down so
we can call it on prompt hold began.
This will also get passed a prompt object proximity prompt and it also gets passed a player.
We'll need a function for disabling all of our tasks.
And then we're also going to need a function for setting up our tasks.
Now something important for us to do is we should also make a function for shuffling an array.
So this function can get past an array.
And what it'll do is it'll return back a different array that's completely shuffled.
And what this will do is it'll take the array that is passed to it, and it's going to shuffle it randomly.
So for example, all of the different positions that we have in the map for our different tasks, when
we loop through them and we start setting, you know, our tasks at those different positions.
If the number of tasks that we have set within our table up here, let's say we only set, you know,
there to be two dirt tasks, but we have six positions that we can place the dirt at.
Well, what we want to do is we want to randomly place our dirt tasks at those different positions.
But when we're looping through it, since it's going to be an array, it's always going to set the tasks
at the exact same position every single time.
So.
So what we need to do is we need to shuffle that table that contains the different positions for those
objects, and then we're able to, you know, position our tasks randomly around the map.
Now we're also going to need a function for getting completed tasks of a particular player so we can
call it get completed tasks from.
And we'll pass a player instance to this.
And then we're also going to need a function to listen to our game comms event.
So on game comms event we'll get past an action here.
And then we're also going to need a function to listen to our Bindable function.
So we can call it on Bindable invoke.
And this also gets passed in action.
And then some arguments to go along with that action.
And then for the public functions we're only going to need an initialize function for our task service.
So init what we need to do is we need to listen to our proximity prompt service.
And there's an event in there called prompt triggered.
And this gets triggered when a user interacts with a prompt.
So any prompt in the game will fire this event.
And we can connect our on prompt triggered function.
We're also going to use an event in here called prompt Buttonholed began.
And this is where we will connect our on prompt hold began function.
Inside of the players service.
We're going to be listening to the player removing event.
And the reason we want to do this is because we want to get the player that left the game, and if they
have a key inside of our player task totals table, then we want to remove them from that table.
We'll want to listen to our Game Comms Bindable dot event, and we'll connect our on game comms event
function.
And then we want to listen to our tasks service Bindable.
And then for the on invoke property, we can set that equal to the on Bindable invoke function.
So let's go ahead and fill out, uh, our on game comms event function.
Why not?
So inside of here, the two actions we want to listen to is inside of game comms enum server dot task
service dot setup tasks.
So when we are told to set up tasks then we can call our setup task function.
Otherwise, if our action is equal to game comms enum server task service dot disable tasks, then we
can call our disable tasks function.
So let's go ahead and fill out our setup tasks function.
Inside of here what we need to do is we need to loop through every single location or possible task
location inside of a server storage dot task part positions.
And we're going to get all of the children in there.
And now, since there's four separate folders for different task locations, then that means we're going
to have to loop through each one of those different folders.
So we're getting past four folders in this for loop.
So we're going to loop through every single position inside of that task location folder get children.
So we're looping through this folder right here which gives us four different folders.
And then we're looping through each one of these folders to get to the different positions.
Now as I said, it's important that we shuffle this table right here because we're always going to be
return an array starting from the top to the bottom.
So if we want to randomly place our tasks around the map, we need to go ahead and make this array,
you know, random.
So what we could do is we could call our shuffle function here and pass this table to it.
And this will return back to us an array that is shuffled.
Now inside of the shuffle function.
What we need to do is we need to loop through every single index value pair in our array.
So we'll start the index at one, and we'll loop all the way to the length of our array minus one.
Because what we're going to be doing is we're going to be swapping positions of values in the table
randomly.
So we don't need to go to the very last one, because when we swap two different positions, it's also
going to include that last value, which is why we're subtracting it by one here.
And what we're going to do is we're going to generate a random number.
So we'll call it random index equal to RNG next integer.
And we're going to pass one and get the length of our array.
And then we're also going to get the value that is currently stored within our array at the index we're
at in this for loop.
Because now what we're going to do is we're going to set inside of our array at the current index.
We're going to set it equal to whatever value is stored inside of our array at this random index.
And then once we do that at our random index, we're going to set it equal to the value that we just
stored here.
So you can basically think of us randomly swapping the values, uh inside of our array.
And then once we're done with that, we can go ahead and return the array at the end.
So basically if we passed a table like one, two, three and four, this is going to loop through each
value.
And it's going to randomly swap the positions of these values.
So we might get an output that's completely different like 312 and four something like that.
That's the whole purpose of our nice little shuffle function here.
So now that we got this shuffled array, what we can do is we first want to check inside of our total
task table.
We're going to pass this task locations name which matches what we have in the table.
And we're going to check the total.
And if this total is greater than or equal to total tasks.
Task location dot name dot max.
So if we're already at the max amount of tasks for this particular position, then we're just going
to break out of this for loop and move to the next task location.
Otherwise, what we're going to do is we're going to create a clone of the task object we need to fulfill
at this position.
So inside of server storage dot task parts, we're going to pass the task location dot name.
So we're getting whatever task part based on the name of the location.
And then we're going to clone it.
Then we can set the position of this clone equal to the position of our part.
Now if this task location dot name is not equal to dirty water.
Then what we want to do is we want to randomly rotate it so it's not always the same, right?
We don't want to make it look like we copy and pasted the same task all over the place, but if we rotate
it randomly, then it makes it look a little bit nicer, so we can get our clone and we can change the
rotation to be equal to a vector three dot new.
For the x axis we don't care, but for the y axis we can do rng next integer and rotate it randomly
360 degrees and then zero for the z axis.
And then afterwards, we can set the parent of our clone equal to the workspace Krusty Krab.
And there's a folder in there called tasks.
And now that we've placed it on the map, we want to update the total value inside of our Total tasks
table.
So we'll just copy this and set the total plus equal to one.
Then what we could do is we could use our update guy event and fire to all of the clients that they
need to do the GUI actions enum of update tasks.
So we're going to be adding a whole bunch of tasks to their GUI, and we're going to have to pass a
table.
And inside of this table we need different tables to represent each of the different tasks.
Right.
So up here, this first task that we could pass the name of this one is going to be dirt, because it's
the dirt task.
And the text for this task is going to be inside of the tasks.
Dot dirt, dot text.
And then we're going to concatenate this with the total tasks dot dirt.
And get the fulfilled number.
And then we can concatenate that with a slash and then concatenate that with the total task dot dirt
dot total.
So how many have we fulfilled out of the total.
And then we could just basically do this exact same thing for the other tasks.
So we'll just paste this in here four times.
We'll change this one to the crumbs task.
This will be tasks dot crumbs dot text.
And we'll get the amount that we have fulfilled for the crumbs and then the total.
We'll do the same thing for the dirty water or toilet task.
So tasked.
Dirty water.
And then here we got to do the same thing.
Dirty water.
Now for our food crates.
It's going to be a little bit different, and that's because we do not want to update the total for
this task based on how many crates are on the map.
Instead, we want the max value here to represent how many cans of food we need to put inside of the
fridge here.
So basically what we need to do.
Is we need to set the total tasks dot food crates dot total equal to the total tasks dot food crates
dot max value.
Because the max value is going to define for us how many food items we need to put in the fridge, instead
of how many food crates we need to put on the map.
Because we're always going to put four food crates on the map.
But this number here reflects how many different items out of those crates that we have to put into
our fridge.
Now we can go ahead and pass food crates as the name for this one.
And then, of course, we're going to have to get the task for the food crates.
And then we'll pass the fulfilled slash food crates dot total.
So once we have set up all of the tasks, and then we have added the tasks to the player's GUI, the
last thing we need to do is use our game comms event and fire to all of the clients using the game comms
enum client dot two client dot play sound.
And the sound that we're going to play is going to be the music.
So we're going to pass the chosen music and then play at point is going to be equal to false, because
we want to play it universally for all the players, and we don't want it to emanate from a specific
point.
So let's actually go ahead and test out what we've gotten done here so far.
Specifically, I want to make sure that our setup tasks function is working correctly.
So when we are told to set up tasks, we're going to call this function, which means we can go back
to our game section module script here.
And we can go back down for when we're starting section one of the game.
And then after the player's ad, you know the tasks objective to their screen.
Then we want to use the game comms event on the server or the Bindable.
And we want to fire using the Game Comms enum server action for the task service.
And we want to let the task service know that it needs to set up all the tasks.
So if we go and play our game.
And we'll wait for all of this stuff to go by real quick.
So once this text goes away, we should get the task system set up.
And there we go.
So now we're having the music played.
As you can see, the task updated on the screen.
Sweep the floor, wipe the tables, clean the toilets and stock the kitchen.
And as you can see, our tasks were randomly placed on the map here.
So for example, here's the one table we need to clean.
Here's the thing that we need to sweep on the floor.
And then we also got food placed here.
Um, unfortunately it looks like we only got one of these food item plates.
And I think that's because of a little bit of a logical error in our for loop.
So we'll have to fix that in a little bit.
And then if we go inside of the bathroom we should have here we go.
One of our toilet tasks as well set up.
Now regarding that issue we have where we're not getting all of the crates placed on the map.
Uh, I think the issue is because we're prematurely breaking out of this for loop here, because we're
updating the total for every single task, including the food crates task, which we don't want to do.
So before we actually update the total here, what we could do is we could have an if statement and
make sure that the task location dot name is not equal to food crates.
That way we can actually place all of the food crates that we need on the map that are specified by
the four positions we've set there, so that should fix our food crate problem.
The next thing we want to script is giving players the ability to actually interact with the prompts
of the tasks.
So for example, we can go ahead and fill out our on prompt hold began function.
And what we could do is we could get the object from this prompt so we can call it task object.
And that should be equal to the prompt object dot parent dot parent.
Right.
Since our proximity prompt is in an attachment, the parent is going to be of course the attachment.
And then the parent of the attachment is going to be the task object itself.
From this point, we can check if the task object dot name is equal to something like the dirt task,
because we want to make sure that the player actually has the proper tool to fulfill this task.
We can also do the same for the task object dot name, and this one's going to be the dirty water task.
Because we're checking the name of the task object.
Any other prompts in our game that get triggered or have this function called on them will be ignored
because they get skipped by our if statements here.
Now, if our task object is going to be the dirt task, then we're going to get the tool that's currently
on their character.
So we can do player dot character find first child, which is a tool.
And we need to check if this tool matches the tool required for this task.
So if they don't have a tool on their character, or let's say the tool on their character is not equal
to the one specified within our tasks table.
So we can pass task object dot name and then get the required tool for this task.
If it's not matching, then we can update this player.
So Fhir client and we're going to pass this player GUI actions enum.
And then we're going to do the small message and we're going to tell them.
That you need a broom.
For this task, and then we'll make sure to return out of the function.
And then we can just basically copy this and then paste this here.
And let me make sure to rename this to Dirty Water.
It's very important to match the strings.
And after we check the tool here we want to make sure to change the text to tell them that they need
a toilet brush for this task.
And that's all we need to do for this function.
Now inside of our on prompt triggered function we're going to do the same thing.
We're going to get the task object from the prompt object dot parent dot parent.
And the first thing what we want to do is we want to check if this player has a key within the player
task totals table.
So if they don't.
So inside of player task totals, if we pass their name and they don't have a key in there, then we
need to set one up for them.
So we'll copy this.
And what we could do is we could set a table for them.
And in here it's going to store how many dirt tasks they completed, how many crumbs tasks they completed,
how many dirty water tasks they completed, and then how many food crates tasks they completed.
From this point, we're going to check if the task object dot name is equal to food crates.
So if they trigger the prompt inside of the food crates, then we need to give them, you know, a food
object.
Now the first thing we need to check on this food crate is whether or not it has enough stock.
So if we actually go inside of server storage and we check our food crates, there's some attributes
in here that tells us how much stock is left in the crate and the max stock for the crate.
So if this task object get attribute stock left.
Is equal to zero, then we're just going to return out of this function because we don't care about
this prompt.
Otherwise, if they aren't out of stock, then we're just going to check to see whether or not a player
already has a food item tool on them.
So inside of the player's backpack we're going to find First Child.
And the name for this tool is called food.
So if they already have it in their backpack or they're already holding one.
So player dot character find first child food.
So if they already have this tool then we're just going to use the update guy event and tell this player
that, hey, you can't grab any more stock because you're already holding some.
So we can do guy actions enum dot small message and give them a message like you already have food on
you and then we can return because we don't care about that either.
Otherwise if they don't have the tool then we need to give it to them.
So first we're going to use our game comms event and fire to all the clients to play a sound.
So game comms enum client dot two client dot play sound.
And the sound we want to play is going to be equal to the tasks.
We're going to pass the task object dot name.
And then we're going to get the collection sound play at point.
We're going to set that to be true.
And the position we want to play it at is going to be equal to the task object dot position.
The next thing we could do is inside of the task object.
We can set the attribute of stock left.
Equal to the task object.
Get attribute stock left and we're going to subtract this by one.
So actually uh what we could do is we could store the stock left in a variable.
So stock left is equal to.
We'll copy this, paste that here, and then we can just copy the name of this variable and compare
it here.
And then we'll just paste that here.
So we're reducing the stock on our task object.
And then we're going to update the object text within our proximity prompt.
So prompt object dot object text.
We're going to set it equal to food left.
And we can concatenate this with the updated stock.
So task object get attribute stock left.
Concatenate that with a slash and then concatenate that with the task object get attribute max stock.
Because inside of our fruit crates and inside of the attachments, there will be a string in there that
tells us how much food is left, and we need to update it every single time a player grabs food out
of it.
After that, we can get a clone of this tool we need.
So in server storage and the tools folder dot tasks, there's a food tool.
We're going to clone that.
And then we're going to give it to the player.
So player dot backpack.
The next prompt we need to specifically listen for is to see if the prompt object is equal to our refill
prompt.
Or basically this player has gone up to the fridge and activated the refill prompt.
So we need to check if they actually have food on them.
So we're going to check to see if they're holding it.
So player dot character find first child food.
If they do not have a food tool, then we're going to use the update GUI event and fire to this particular
player.
And we're going to give them a message, and we're going to tell them you have nothing to restock with.
You have nothing at all.
And then we're going to return.
Otherwise we can use our game comms event.
And we can fire to all the clients in the game to play another sound.
So game comms enum for the client two client play sound.
The sound for this one is going to be equal to tasks.
Dot food crates dot completion sound.
Play at.
Point is going to be true, and the position is going to be equal to the task object dot position.
And then we can destroy this tool out of the players hands.
And then we want to set total tasks dot food crates dot fulfilled plus equal to one.
And then for this particular player we want to, you know give them the credit for completing this task.
So player task totals will pass the player dot name.
And we'll get their food crates and set that equal plus equal to one.
Now each time a food task is completed, we need to check whether or not that we have reached, you
know, the total amount of food crate tasks we need to complete.
So if total tasks dot food crates dot fulfilled is equal to total tasks dot food crates dot total.
Then we're going to set the refill prompt dot enabled equal to false.
And then we're going to use the update GUI event and fire to all of the clients that we fulfilled a
task.
So GUI actions enum dot task fulfilled.
And the fulfilled task is going to be our food crates task.
And we can set the text for that one to be equal to the task.
Dot food crates dot text.
And then the total tasks dot food crates dot fulfilled will concatenate that with a slash and then concatenate
that with the total tasks.
Dot food crates dot total.
So this will make that task on the screen appear green, and then it'll update it with the new amount.
So if we fulfilled three out of three, that's what it'll display on the screen.
Otherwise, if we didn't, uh, fulfill the task, we still need to update the task on the client side
to stay consistent with the tasks that have been completed.
So we're just going to copy this, but instead we're going to give them the action of update task.
So we need to update a specific task.
And that task to update is food crates.
And we're just updating the text for that one as well.
Okay.
So now that we have made these two specific special checks just for our food crates task, what we can
do here is just create an if statement for every other single task.
So if this, uh, task object is inside of our total task table.
So we're going to pass the task objectname.
If there's a key inside of that table, then what we need to do is we need to check if tasks task Objectname
has a required tool.
If they do, then we need to check if this tool is on the player's character or they have it equipped.
So player character find first child, which is a tool.
If they do not have a tool on our character, or the tool on the character name is not equal to the
task's task object.
Dot name dot required tool.
Then we need to use the update UI event and fire to this particular player that they cannot complete
the task.
So GUI actions dot small message, and the message we're going to give them is you do not have the required
tool needed to complete this task.
Otherwise we can set total tasks.
Pass task Objectname dot fulfilled plus equal one.
And then we also got to give him credit for it as well.
So task totals pass the player name.
And then we're also going to pass here the task object dot name.
And then we'll set that plus equal to one as well.
And then we need to check if this particular task has a completion sound.
So if tasks pass task object dot name dot completion sound then we need to use the game comms event
and fire to all the clients to play a sound.
So game comms enum client dot two client dot play sound.
The sound is going to be equal to the tasks.
Task object dot name.
And that's going to be the completion sound.
We can set play at point equal to true.
And the point is going to be equal to the task object dot position.
Afterwards, we can have another if statement to check whether or not, um, this task was fulfilled.
So if total tasks task object dot name dot fulfilled.
Is equal to the total tasks task.
Objectname yeah, I know this is getting pretty redundant, but total.
So if we completed all the tasks necessary, then we can use the update UI event and tell them that
they fulfilled the task.
So I'm just going to copy this up here real quick.
And we can paste that here.
And the fulfill task is going to be equal to the task Objectname.
And then the text is going to be equal to tasks pass task objects and then get the text.
And then we'll just copy this and paste that here.
Not fulfilled and then paste that here as well.
Otherwise, if we didn't fulfill the task, then we can just do the exact same thing, but instead we
need to update the task.
So.
Update task.
Task to update and we should be good to go there.
And then after we have completed this particular task object, we need to go ahead and destroy it off
the map.
So task object destroy.
After all of that, the last thing we need to check is if we have completed all of the tasks in our
game.
So if we call our check task completion function and that returns true.
Then we can use the game, combined a ball and fire to let our game section function know that all of
the tasks have been completed, and this function can continue on executing because the plan is is that
once we tell the task service to set up tasks, this is going to sit here and yield until either we
reach a timeout or we get a message back from the task service telling us that all the tasks have been
completed so we can fire and pass the game comms enum server, and we can create a key for our game
service.
So inside of the game Communication enum, I'll create a new section for game service.
And in here we can give them the action that we completed all of the tasks.
So game service not completed tasks.
Now, something that's important to note is that if you remember, this function is going to get called
every single time a player interacts with a proximity prompt in our game.
Doesn't matter what the prompt is.
So we need to ensure that this particular prompt is actually equal to a task object prompt or our Re-fill
prompt, because we don't want to keep, you know, firing this event every single time that this function
gets called, even after all of our tasks have been completed.
So we need to ensure that inside of our tasks table, there is a key for this task object dot name.
Or we need to make sure that this prompt object is equal to our Re-fill prompt.
And then we also need to make sure that we have completed all of our tasks.
If so, then we can go ahead and fire this Bindable.
Now let's go ahead and fill out our check task completion function real quick.
And this one should be relatively easy to do, because all we're going to do is we're going to loop
through every single, uh, task.
Actually we can't name it that, so we'll just name it T for short and total tasks.
What we're going to do is we're going to check if the total is not equal to the fulfilled value.
If it is, then we're just going to return false because clearly we haven't completed all of our tasks
yet.
But if we loop through every single task and all of them have been fulfilled, then we can go ahead
and return true.
Already in.
The next function that I think we can fill out is our disable tasks function.
So this one should be pretty easy to do.
All we're going to do is loop through every single task object inside of our workspace, not Krusty
Krab dot task folder.
We're going to get all the children in there.
And what we're going to do is we're going to get this task object, get the attachment that's inside
of it, and we're going to set the proximity prompt dot enabled equal to false.
Afterwards we can set the Re-fill prompt dot enabled equal to false as well.
And then we're going to use the update UI event and fire to all of the clients in our game to go ahead
and hide their task frame.
So high task frame.
And then we're also going to have to use the game comms event and fire to all of the clients.
To stop playing the task music, because those sound instances have the loop property enabled, so they're
going to be playing forever and ever unless we explicitly tell those clients to stop playing the sound.
So game comms enum client dot two client.
We're going to give them the action to stop the sound.
And the sound we wish to stop playing is going to be the chosen music, and we should be good to go
there.
Okay.
The other functions we can go ahead and fill out is our get completed tasks from function and the Bindable
invoke function.
So when this function gets called, we want to get the total amount of tasks that this player completed.
And this one is going to be really easy.
All we're going to do is we're going to return if inside of the player task totals.
This player has a key in their.
Then we're going to basically just return the table that's inside of player task totals for this particular
player.
Otherwise, if they didn't have a key inside of the player task totals table, then we're just going
to return a table and we can have a key in there that's like completed tasks.
And we'll just set that to zero.
So just in case this player never had a table to begin with, we're just going to give them a table
with zero completed tasks.
Then inside of our on bind invoke function, the action we need to listen to in here is our game comms
enum server dot task service dot get completed tasks for player, and all we're going to do in here
is return true to let them know that this executed successfully, and we're going to return whatever
gets returned from our get completed tasks from.
And then this, uh, action needs to be supplied.
The player we need to get the tasks for.
So inside of the args table, the first key can just be our player object.
So whatever script, uh, executes this function, they'll just pass a table with that player inside
of it and then we return back to them.
That player's completed task.
Otherwise at the end here we're just going to error.
We'll give a message.
We'll say requested action.
We'll put a directive did not match possible actions for.
And then we'll put another directive.
And we'll format this with the two string.
And we'll pass the action here.
And then we'll just pass the script dot name.
So for some reason a developer gives us an action that's incorrect.
Like maybe they accidentally passed set up tasks to our Bindable invoke function.
It'll say requested action, set up tasks did not match possible actions for tasks service.
And that's the error we'll get for our bind double invoke function.
Okay.
And our task service should be all set up.
So now it is time to test whether or not everything is working correctly for our tasks.
All right.
So our music is playing, as you can see.
Perfect.
We have all of our four crates here.
Um, unfortunately, it looks like our main door didn't shut for some reason.
That's kind of interesting.
But anyways, uh, we have each of our crates here, and as you can see, it tells us how much food
is left inside of them.
So if I actually interact with this.
There we go.
We get the food given to us, and if we go ahead and go to the kitchen, we should be able to refill
our fridge.
So there we go.
It took our can, but unfortunately it did not update the tasks for that particular objective.
But it is updating the text inside of these proximity prompts and it's not giving me any extra ones.
And it's telling me you already have food on you.
All right, let's go back.
It did disable the prompt though, because we did fulfill the task, but unfortunately it didn't update
on our screen.
And it does look like we're having our small message text on the bottom of our screen staying stuck
for some reason.
So that's another problem we're going to have to fix.
So let's actually let's go ahead and troubleshoot these real quick.
Alrighty.
So the problem here on the client is that inside of our main UI handler, we actually did not add a
key inside of our case table for when we fulfill a task.
So let's add that real quick.
So GUI actions enum.
Dot task fulfilled.
We need that to refer to our fulfill task function.
All right.
Good to go there.
And then for our display.
Small message.
Unfortunately it does not fade out.
So let's check our logic here real quick.
And I don't see any issues really with our logic here.
So what I could do maybe that error was a fluke for some reason.
But we can print out the small message label dot transparency.
And we can also print out the small message label dot text as well as the text that it's supposed to
match, just to see what these values are exactly for, why this is not fading out.
And we can go ahead and try this out again.
That is strange.
Our door closed this time, so I'm not sure exactly why the door didn't close last time, but if I interact
with it, hopefully we can see why our text isn't fading out.
Okay, this is interesting.
It's printing out one for the transparency of our text, which means our text should be invisible right
now, but it isn't.
So let's check why real quick.
And let's see here.
Oh, it's because I'm a goofball.
Um, we need to check the text transparency of our text and not the transparency.
So we need to change this to text transparency.
And now our text should be able to fade out.
Very simple little mistake.
But something like that can cause a huge headache.
So yeah, make sure we'll change this from transparency to text transparency inside of our main UI handler
and the display small message function.
Okay, let's try this out again.
All right.
Unfortunately, our door did not close again.
And I think the problem with our door is that because we are checking whether or not the door is moving
when we're trying to close it, it doesn't allow us to close the door.
So it appears we might need to remove that if statement when we're trying to close the door from the
server side.
But we'll fix that in a moment.
But we need to check whether when interacting with this prompt, if this is going to disappear.
So this should fade out.
Should fade out any second okay.
There we go.
Perfect.
It fades out if we grab food here and we go to fulfill the task inside of the kitchen, we go do that.
Okay, there we go.
Our task turns green and it updates the count one out of one.
And as you can see, the prompt has disappeared because we've fulfilled that task.
It's also disappeared off of our tasks.
G1 now, if we try to clean the floor, we should get another message.
There we go.
You need a broom for this task and if I try to complete it.
You do not have the required tool needed to complete this task.
Perfect, because we actually need a broom tool.
Now, I've already left these scripts inside of the model or all of the game assets for this game.
It's a very simple script inside of this tool, all it does is just grabs the tool from the workspace
and copies it into the player's inventory when this is clicked.
But now we get our broom.
And if we go over, as you can see, we don't get the message on our screen anymore.
And we unfortunately aren't able to clean up.
Looks like we did get another error in our on prompt triggered function, so we'll fix that in a moment.
But let's go ahead and test out our other, for example our toilet brush.
So let's find where our toilet that needs to be scrubbed is at.
Here we go.
So if we go and clean this toilet.
We get the same error, so we'll fix that in a moment.
Let's go ahead and try out.
This is probably going to give us the same error as well if we try to complete this one.
So we're getting the same error attempt to index nil with text.
So let's go ahead and see what the problem is there okay.
So at line 127 we're getting an error attempt to index nil with text.
So when we index with text here, apparently this is nil.
And that's of course because we didn't pass the name of our task object.
We forgot to pass the name.
And while we're at it, we're also going to go into server script service and we're going to open up
our door service.
And when we want to open and close a door, what we're going to do is we're actually just going to go
ahead and get rid of these if statements of whether or not the door is moving.
So we'll get rid of it out of the close function, and we'll also get rid of it out of the open function.
This means that our front door shouldn't get left open when we touch that part, and the server tries
to close it, okay, fix that as well.
Okay.
So the problem was, is that when I open this door, right, I touch that part inside immediately while
the door was still opening.
So let me open this door and sprint in real fast.
So we'll do that and hopefully the door gets closed.
So we're going to have to wait through this text.
Okay.
If I look behind me.
Perfect.
Our door is indeed closed.
We should be able to fulfill these tasks.
No problem now.
So if I try to clean up this spill on the floor, hopefully we don't get an error.
And unfortunately we did get another error.
This time it's different.
One attempt to index nil will fulfill.
I think we forgot to pass the name of our object again.
So let's hop back into our script I guess.
And of course, we accidentally did the exact same stupid problem here.
And we also did it over here.
So we need to copy this and make sure we're passing the task object name.
Inside of this table instead of the task object itself.
Okay, fix that several more times.
Hopefully.
Hopefully now.
Our problems should be fixed.
So let's go ahead and play test one more time.
Okay.
We get our broom.
If we go clean up this mess here, hopefully we don't get an error.
No error.
Please.
There we go.
All right.
We successfully completed the task.
As you can see, it fulfilled on the top, right.
And that means we should be able to clean our table now.
And unfortunately, when we do it with the crumbs, absolutely nothing happens.
That's another problem.
Looks like we're going to have to figure out why that's not working.
But hopefully, maybe our toilet should be working.
So if we go ahead and find which one, here it is.
We clean this toilet.
Hopefully we don't get an error.
Perfect.
We clean the toilet, the fills on the top right.
All is good there.
If we grab food from here, we get our food.
And then we go and fill that in the kitchen here.
Perfect.
That works just as well.
But unfortunately, it appears that our crumbs.
Are not wanting to be clean.
So back inside of the task service, inside of our on prompt triggered function, we're going to go
back down here where specific tasks such as the dirty water, the crumbs or the broom tasks need to
be fulfilled and we need to figure out why exactly it's working for the other two, but it's not working
for the crumbs task.
So if I look quickly over this.
Oh.
Um, for some reason, we accidentally indented every single thing.
Inside of this if statement that checks whether or not this task needs a required tool.
And since our crumbs don't require a tool, nothing is being executed at all because it doesn't go into
this if statement.
So that's a little bit of an issue.
So what we need to do is we need to copy this and take it and move it out of our if statement and put
this down here, because here is where we specifically check for whether or not the player has the tool
requirements for this task.
And then after that we can go down and fulfill the particular task.
So now our crumb task should be working and our other tasks should be working as well.
Okay.
Now that's an example of a logical error.
Our code not performing the way we expect it to.
Now hopefully everything should be fixed.
Okay, hopefully our crumb task should be working now.
So let's go ahead and find it wherever it's at.
Here it is.
All right.
Please be working.
Perfect.
It works great.
We completed it in the top right.
And then let's go ahead and see if we can complete the other tasks if they're still working.
So if we go and sweep this up here should fulfill as well.
Perfect.
Fulfilled.
If we go and restock the kitchen we should be good.
So we grab our food, we go back into the kitchen.
Okay, perfect.
We refilled it.
And let's go ahead and test out our toilet task.
Find out where it's at.
Here it is.
Clean that up.
And perfect.
All right.
Our task service seems to be working great.
Okay, this lecture got quite long, but you can obviously see the amount of time that it can take to
script and debug our code.
We're going to continue working on our story in the next lecture.
So thanks for sticking around and I'll see you in the next one.